# 作者:龙炜轩
#！ 教学用多字图绘制脚本
# 这个脚本可以解决什么问题？
# 解决线条样式选择困难症 + 单独绘制效率慢

# import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from numpy.random.mtrand import randint  # 从numpy.random.mtrand模块导入randint函数，用于生成随机整数

# 1. 声明
# 定义一个恒定的x轴数据
x = np.arange(0, 10, 1, dtype=np.int16)

# 绘制多子图上的超级标题(非必要)
# 中文标题需要设置字体


# 定义4个y轴数据，作为测试数据
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = np.exp(x)

# 统一存进复杂数据结构内方便访问
ys = [y1, y2, y3, y4]
'''存储所有y轴数据'''

# 定义一个子图绘制类
class SubplotImage:
    def __init__(self, x, ys, suptitle):
        self.x = x
        self.ys = ys
        self.suptitle = suptitle
    
    def subplotImage(self):
        '''绘制多子图上的图像'''

        # 超过六张子图时，需要手动调整子图布局
        if len(self.ys) > 6:
            plt.subplots_adjust(hspace=0.5)
        
        # 十张子图退出
        if len(self.ys) > 10:
            print("最多只能绘制10张子图")
            return

        # 初始化已用样式列表
        usedStyles = []
        plt.rcParams['font.sans-serif'] = ['SimHei']    
        plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
        plt.suptitle(self.suptitle)
        
        for i in range(len(self.ys)):  # 几个测试用例函数就循环几次
            plt.subplot(2, 2, i+1)
            
            # 令颜色随机（10中线条样式）
            lineStyles = ['ko--', 'r--', 'go--', 'b-', 'm*-', 'c^--', 'y*-', 'k.-', 'rs-', 'bp--', 'g^-']

            # 用条件语句判断是否重复选用相同样式，如相同则重新搜索新样式，循环往复。
            style = lineStyles[randint(0, len(lineStyles))]  # 区间内随机索引一个样式
            
            # 检查样式是否被选用过，如是则随机搜索直至新样式，循环往复。
            while style in usedStyles:
                style = lineStyles[randint(0, len(lineStyles))]
            
            usedStyles.append(style)
            plt.plot(self.x, self.ys[i], style, label=f"f$y{i+1}$")  # 令标签打印函数名
            plt.title(f"y{i+1}")
            plt.legend()
            
            # 绘制网格
            plt.grid()
        
        plt.show()
    
# 2. 定义函数
'''该变量用于记录选用过的线条样式，下次不再选用'''

def subplotImage(x, ys, suptitle):
    '''绘制多子图上的图像'''

    # 超过六张子图时，需要手动调整子图布局
    if len(ys) > 6:
        plt.subplots_adjust(hspace=0.5)
    
    # 十张子图退出
    if len(ys) > 10:
        print("最多只能绘制10张子图")
        return

    # 初始化已用样式列表
    usedStyles = []
    plt.rcParams['font.sans-serif'] = ['SimHei']    
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
    plt.suptitle(suptitle)
    
    for i in range(len(ys)):  # 几个测试用例函数就循环几次
        plt.subplot(2, 2, i+1)
        
        # 令颜色随机（10中线条样式）
        lineStyles = ['ko--', 'r--', 'go--', 'b-', 'm*-', 'c^--', 'y*-', 'k.-', 'rs-', 'bp--', 'g^-']

        # 用条件语句判断是否重复选用相同样式，如相同则重新搜索新样式，循环往复。
        style = lineStyles[randint(0, len(lineStyles))]  # 区间内随机索引一个样式
        
        # 检查样式是否被选用过，如是则随机搜索直至新样式，循环往复。
        while style in usedStyles:
            style = lineStyles[randint(0, len(lineStyles))]
        
        usedStyles.append(style)
        plt.plot(x, ys[i], style, label=f"f$y{i+1}$")  # 令标签打印函数名
        plt.title(f"y{i+1}")
        plt.legend()
        
        # 绘制网格
        plt.grid()
    
    plt.show()

# 3. 主流程
if __name__ == "__main__":
    # 1. 声明
    # 定义一个恒定的x轴数据
    x = np.arange(0, 10, 1, dtype=np.int16)

    # 绘制多子图上的超级标题(非必要)
    # 中文标题需要设置字体

    # 定义4个y轴数据，作为测试数据
    y1 = np.sin(x)
    y2 = np.cos(x)
    y3 = np.tan(x)
    y4 = np.exp(x)
    
    # 统一存进复杂数据结构内方便访问
    ys = [y1, y2, y3, y4]
    
    subplotImage(x, ys, "多子图绘制脚本")
    a = SubplotImage(x, ys, "多子图绘制类方法")
    a.subplotImage()